#ifndef _LIST_H_
#define _LIST_H_

struct list_head
{
	struct list_head * prev;
	struct list_head * next;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) } 
#define LIST_HEAD_DEFINE(head)	struct list_head head

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name) 

/*
1.向链表中添加节点,普通的在两个非空结点中插入一个结点，注意new、prev、next都不能是空值
2.Prev可以等于next，此时在只含头节点的链表中插入新节点。
3.只有头结点的时候，头部插入和尾部插入没有区别
*/
static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
{ 
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
} 

//头部插入，插在头结点之后，
static inline void list_add_head(struct list_head *new, struct list_head *head) 
{ 
	__list_add(new, head, head->next);
} 

//尾部插入，插在最后一个元素之后
static inline void list_add_tail(struct list_head *new, struct list_head *head) 
{ 
	__list_add(new, head->prev, head);
}

/*
从链表中删除节点
*/
static inline void __list_del(struct list_head * prev, struct list_head * next) 
{ 
	next->prev = prev; 
	prev->next = next; 
}

//删除entry所指的结点，同时将entry所指向的结点指针域封死
static inline void list_del(struct list_head *entry) 
{ 
	__list_del(entry->prev, entry->next);
	entry->next = NULL;
	entry->prev = NULL;
}

//移动节点
//将entry所指向的结点移动到head所指向的结点的后面。 
static inline void list_move_head(struct list_head *entry, struct list_head *head) 
{ 
	__list_del(entry->prev, entry->next); 
	list_add_head(entry, head);
}

//删除了list所指向的结点，将其插入到head所指向的结点的前面，
//如果head->prev指向链表的尾结点的话，就是将list所指向的结点插入到链表的结尾
static inline void list_move_tail(struct list_head *entry, struct list_head *head) 
{ 
	__list_del(entry->prev, entry->next);
	list_add_tail(entry, head);
}

//判断是否为空链表 
//由list-head构成的双向循环链表中，通常有一个头节点，其不含有有效信息，
//初始化时prev和next都指向自身。判空操作是判断除了头节点外是否有其他节点。 
//试链表是否为空，如果是只有一个结点，head，head->next，head->prev都指向同一个结点，则这里会返回1，
//表示空；但这个空不是没有任何结点，
//而是只有一个头结点，因为头节点只是纯粹的list节点，没有有效信息，故认为为空
static inline int list_empty(const struct list_head *head) 
{ 
	return head->next == head; 
}

static inline int list_empty_careful(const struct list_head *head) 
{ 
	struct list_head *next = head->next;
	return (next == head) && (next == head->prev);
}

//链表合并 
static inline void __list_splice(struct list_head *list, struct list_head *head) 
{ 
	struct list_head *first = list->next; 
	struct list_head *last = list->prev; 
	struct list_head *at = head->next; 
	first->prev = head; 
	head->next = first; 
	last->next = at; 
	at->prev = last; 
}

static inline void list_splice(struct list_head *list, struct list_head *head) 
{ 
	if (!list_empty(list)) 
		__list_splice(list, head);
}

/*
作用：找到成员与结构体开始地址的偏移

TYPE：大结构体的类型
MEMBER：大结构体中成员的名称
*/
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/*
作用：通过成员的指针找到大结构体的指针

ptr 结构体成员的指针
type 大结构体的类型
member ptr代表的成员在大结构体的名称
*/
#define container_of(ptr, type, member) ({                      \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

//链表遍历
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next) 

#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next) 

#define list_entry(ptr, type, member) \
container_of(ptr, type, member)

/*
pos:大结构体的指针
head:头结点
member: struct list_head 在大结构体中的名称
*/
#define list_for_each_entry(pos, head, member) \
    for (pos = list_entry((head)->next, typeof(*pos), member); \
         &pos->member != (head); \
         pos = list_entry(pos->member.next, typeof(*pos), member))

//相比于list_for_each_entry，list_for_each_entry_safe用指针n对链表的下一个数据结构进行了临时存储，
//所以如果在遍历链表的时候需要做删除链表中的当前项操作时，用list_for_each_entry_safe可以安全的删除，
//而不会影响接下来的遍历过程（用n指针可以继续完成接下来的遍历， 而list_for_each_entry则无法继续遍历，
//删除后会导致无法继续遍历）
/*
pos:大结构体的指针
n:大结构体的指针,是一个备份
head:头结点
member: struct list_head 在大结构体中的名称
*/
#define list_for_each_entry_safe(pos, n, head, member)		\
	for (pos = list_entry((head)->next, typeof(*pos), member),	\
		n = list_entry(pos->member.next, typeof(*pos), member);	\
	     &pos->member != (head);					\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

#endif